package com.icesoft.base.manager.security.login.phone;

import com.icesoft.base.manager.security.suppose.IUserDetailsService;
import com.icesoft.core.web.suppose.sms.config.SmsCodeCacheService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AccountStatusUserDetailsChecker;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;
import org.springframework.stereotype.Component;

/**
 * @author 手机登录校验逻辑
 * 验证码登录、社交登录
 */
@Slf4j
@Component
@AllArgsConstructor
public class PhoneAuthenticationProvider implements AuthenticationProvider {
    private final UserDetailsChecker detailsChecker = new AccountStatusUserDetailsChecker();

    private IUserDetailsService userDetailsService;
    private SmsCodeCacheService smsCodeCacheService;

    @Override
    @SneakyThrows
    public Authentication authenticate(Authentication authentication) {
        PhoneAuthenticationToken phoneAuthenticationToken = (PhoneAuthenticationToken) authentication;
        if (phoneAuthenticationToken.getCredentials() == null) {
            throw new AuthenticationServiceException("请提供手机验证码参数");
        }
        String smsCode = phoneAuthenticationToken.getCredentials().toString();
        String phone = phoneAuthenticationToken.getPrincipal().toString();
        if (!smsCodeCacheService.check(phone, smsCode)) {
            throw new AuthenticationServiceException("验证码验证失败");
        }
        smsCodeCacheService.remove(phone);
        UserDetails userDetails = userDetailsService.loadUserByPhone(phone);
        if (userDetails == null) {
            log.debug("用户不存在,phone：{}", phone);
            throw new AuthenticationServiceException("手机号不存在");
        }

        // 检查账号状态
        detailsChecker.check(userDetails);

        PhoneAuthenticationToken authenticationToken = new PhoneAuthenticationToken(userDetails, userDetails.getAuthorities());
        authenticationToken.setDetails(phoneAuthenticationToken.getDetails());
        return authenticationToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return PhoneAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
